package ae.pcfc.etks.online.web.controller.client.company.register;

/* $Id: ClientCompanyRegisterController 
 * Copyright (C) 2011, Trakhees
 *  
 *  History
 *
 * Date  			Author 					Remarks
 * -------------------------------------------------------------
 * April 14, 2011 	Neha_Chauhan 	        Created
 *
 */

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javassist.bytecode.DuplicateMemberException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.UnhandledException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.WebUtils;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WFProcessType;
import ae.pcfc.etks.online.common.delegate.AttachmentTypeDelegate;
import ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate;
import ae.pcfc.etks.online.common.delegate.SecretQuestionDelegate;
import ae.pcfc.etks.online.common.vo.AttachmentTypeVO;
import ae.pcfc.etks.online.common.vo.ClientCompanyReqVO;
import ae.pcfc.etks.online.common.vo.LabelVO;
import ae.pcfc.etks.online.common.vo.SCCompanyVO;
import ae.pcfc.etks.online.common.vo.SecretQuestionVO;
import ae.pcfc.etks.online.common.vo.UploadDocumentVO;
import ae.pcfc.etks.online.web.ConstantsAdmin;
import ae.pcfc.etks.online.web.PageType;
import ae.pcfc.etks.online.web.ViewPath;
import ae.pcfc.etks.online.web.ViewUtils;
import ae.pcfc.etks.online.web.common.Constants;
import ae.pcfc.etks.online.web.controller.BaseController;
import ae.pcfc.etks.online.web.model.ClientCompanyRegistration;
import ae.pcfc.etks.online.web.model.NonClientCompanyRegistrationLicenseInfo;
import ae.pcfc.etks.online.web.util.SecurityUtils;

/**
 * Controller that handles all {@link Company/Registered Client}-related
 * requests, i.e.: all requests for client/company/register/
 * 
 * @author Neha Chauhan
 */

@Controller
@RequestMapping(ViewPath.CLIENT_COMPANY_REGISTER)
public class ClientCompanyRegisterController extends BaseController {

	private ClientRegistrationDelegate clientRegistrationDelegate;
	private SecretQuestionDelegate secretQuestionDelegate;

	@Resource(name = "secretQuestionDelegate")
	public void setSecretQuestionDelegate(
			SecretQuestionDelegate secretQuestionDelegate) {
		this.secretQuestionDelegate = secretQuestionDelegate;
	}

	@Resource(name = "clientRegistrationDelegate")
	public void setClientRegistrationDelegate(
			ClientRegistrationDelegate clientRegistrationDelegate) {
		this.clientRegistrationDelegate = clientRegistrationDelegate;
	}

	private AttachmentTypeDelegate attachmentTypeDelegate;
	private Map<String, String> propertyConstants;

	@Resource(name = "propertyConstants")
	public void setPropertyConstants(Map<String, String> propertyConstants) {
		this.propertyConstants = propertyConstants;
	}

	@Resource(name = "attachmentTypeDelegate")
	public void setAttachmentTypeDelegate(
			AttachmentTypeDelegate attachmentTypeDelegate) {
		this.attachmentTypeDelegate = attachmentTypeDelegate;
	}

	@ModelAttribute(ConstantsAdmin.USER_SECRETQUESTION_REQUEST_MODEL_KEY)
	public List<LabelVO> populateSecretQuestionList() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();

		LabelVO labelVO;
		List<SecretQuestionVO> secretQuestionVOs = secretQuestionDelegate
				.getSecretQuestionList();

		for (SecretQuestionVO secretQuestionVO : secretQuestionVOs) {
			labelVO = getMapper().map(secretQuestionVO, LabelVO.class);
			labelList.add(labelVO);

		}
		return labelList;
	}

	@ModelAttribute(ConstantsAdmin.NON_CLIENT_REGISTRATION_UPLOADDOCUMENT_TYPE_MODEL_KEY)
	public List<LabelVO> populateRegisterClientCompanyUploadDocumentType() {

		List<LabelVO> labelList = new ArrayList<LabelVO>();
		String strAttachmentTypeUser = "CCR";
		List<AttachmentTypeVO> attachmentTypeVOs = attachmentTypeDelegate
				.getAttachmentType(strAttachmentTypeUser);

		LabelVO labelVO;

		for (AttachmentTypeVO attachmentTypeVO : attachmentTypeVOs) {
			labelVO = getMapper().map(attachmentTypeVO, LabelVO.class);
			labelList.add(labelVO);
		}

		return labelList;
	}

	@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTER_SUMMARY_REQUEST_MODEL_KEY)
	public SCCompanyVO populateReferenceData(HttpServletRequest request,
			@RequestParam(value = "clientId", required = false) String id) {

		if (id != null) {
			String trakheesId = SecurityUtils.decrypt(id);
			SCCompanyVO scCompanyVO = clientRegistrationDelegate
					.findSCCompanyByTrakheesId(trakheesId);

			if (scCompanyVO == null)
				throw new UnhandledException("Invalid trakhees Id no: "
						+ trakheesId, null);

			return scCompanyVO;
		}

		return null;
	}

	/**
	 * Custom handler for displaying the form, i.e.: GET requests for
	 * client/company/register/form.jsp
	 * 
	 * @see #form(HttpServletRequest,SessionStatus,ClientCompanyRegistration,
	 *      BindingResult)
	 * @see WEB-INF/jsp/client/company/register/form.jsp
	 */

	@RequestMapping(value = "/form.htm", method = RequestMethod.GET)
	public void form(
			@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) ClientCompanyRegistration command) {

	}

	@RequestMapping(params = { "Upload" }, method = RequestMethod.POST, value = "/form.htm")
	public String uploadForm(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) @Valid ClientCompanyRegistration clientCompanyRegistrationInfo,
			BindingResult errors, Model model) throws Exception {

		boolean isUpload = WebUtils.hasSubmitParameter(request,
				ConstantsAdmin.UPLOAD_BUTTON);

		try {

			if (isUpload) {
				if (errors.hasErrors()) {
					return ViewUtils.DEFAULT_VIEW;
				} else {

					if (uploadDocuments(request, status,
							clientCompanyRegistrationInfo)) {
						request.setAttribute(ConstantsAdmin.SUCCESS_PARAM,
								clientCompanyRegistrationInfo
										.getStrUploadDocumentType());
						return ViewUtils.DEFAULT_VIEW;

					} else {
						request.setAttribute(ConstantsAdmin.ERROR_PARAM,
								ConstantsAdmin.ERROR_PARAM);
						String[] messageArgs = new String[] { getMessageSource()
								.getMessage("label.company.uploaddocuments",
										null,
										RequestContextUtils.getLocale(request)) };
						errors.reject("error.file.not.selected", messageArgs,
								null);
					}

				}
			}

		} catch (DuplicateMemberException dme) {
			request.setAttribute(ConstantsAdmin.ERROR_PARAM,
					ConstantsAdmin.ERROR_PARAM);
			String[] messageArgs = new String[] { getMessageSource()
					.getMessage("label.company.uploaddocuments", null,
							RequestContextUtils.getLocale(request)) };

			errors.reject("error.repeat", messageArgs, null);
		}

		catch (Exception e) {

			e.printStackTrace();
		}

		return ViewUtils.DEFAULT_VIEW;
	}

	/**
	 * Custom handler for displaying the form, i.e.: POST requests for
	 * client/company/register/form.jsp
	 * 
	 * @see #form(NonClientCompanyRegistrationLicenseInfo)
	 * @see WEB-INF/jsp/client/company/register/form.jsp
	 */

	@RequestMapping(method = RequestMethod.POST, value = "/form.htm")
	public String form(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) @Valid ClientCompanyRegistration clientCompanyRegistrationInfo,
			BindingResult errors) throws Exception {

		if (errors.hasErrors()) {
			return ViewUtils.DEFAULT_VIEW;
		}

		StringBuffer message = new StringBuffer("");
		if (validateClientAdminDocuments(request, status,
				clientCompanyRegistrationInfo, message)) {
			for (UploadDocumentVO documentVO : clientCompanyRegistrationInfo
					.getArrDocumentVOs()) {
				String companyFolderPath = propertyConstants
						.get(ConstantsAdmin.UPLOAD_USER_FILES_PATH_KEY);
				String tempFolderPath = propertyConstants
						.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);

				File uploadedFile = new File(tempFolderPath
						+ documentVO.getStrTempFileName());
				File uploadFile = new File(companyFolderPath
						+ clientCompanyRegistrationInfo.getStrCompNameEng()
						+ documentVO.getStrName());

				FileUtils.copyFile(uploadedFile, uploadFile);
			}
			ClientCompanyReqVO clientCompanyReqVO = new ClientCompanyReqVO();

			// clientCompanyReqVO.setStrProcessCode(ConstantsAdmin.PROCESS_CODE_CLIENT_COMPANY_REGISTRATION);
			clientCompanyReqVO
					.setProcessCode(WFProcessType.CLIENT_COMPANY_REGISTRATION);
			clientCompanyReqVO
					.setStrProcessStep(ConstantsAdmin.PROCESS_STEP_INITIATE_CLIENT_COMPANY);
			clientCompanyReqVO.setApplicationDate(Calendar.getInstance()
					.getTime());
			clientCompanyReqVO
					.setStrWFinitatedBy(ConstantsAdmin.CLIENT_COMPANY_WORK_FLOW_INITIATE);
			clientCompanyReqVO.setStrWfStatus(ConstantsCommon.IN_PROGRESS);
			clientCompanyReqVO.setStrStatusEn(this.getMessageSource()
					.getMessage("msg.workflow.status.in.progress", null,
							Locale.ENGLISH));
			clientCompanyReqVO.setStrStatusAr(this.getMessageSource()
					.getMessage("msg.workflow.status.in.progress", null,
							new Locale(Constants.LOCALE_ARABIC)));
			clientCompanyReqVO.setStrClientType(Constants.COMPANY);
			clientCompanyReqVO.setCreateDate(Calendar.getInstance().getTime());
			clientCompanyReqVO.setStrStatus(Constants.ACTIVE);
			clientCompanyReqVO.setStrType(Constants.COMPANY);

			getMapper().map(clientCompanyRegistrationInfo, clientCompanyReqVO);
			
			clientCompanyReqVO.setStrPassword(SecurityUtils
					.hashPassword(clientCompanyRegistrationInfo
							.getStrPassword()));
			clientCompanyReqVO.setStrTrakheesId(SecurityUtils.decrypt(request
					.getParameter("clientId")));
			String refNo = clientRegistrationDelegate
					.registerCompany(clientCompanyReqVO);

			Map<String, String> paramMap = new HashMap<String, String>();
			paramMap.put(ConstantsAdmin.REFRENCE_NO, SecurityUtils.encryptQueryParam(refNo));

			return ViewUtils.getRedirect(ViewPath.CONFIRMATION, PageType.SHOW,
					paramMap);

		} else {
			String[] messageArgs = new String[] { getMessageSource()
					.getMessage("label.company.uploaddocuments", null,
							RequestContextUtils.getLocale(request)) };
			errors.reject(message.toString(), messageArgs, null);
			return ViewUtils.DEFAULT_VIEW;
		}
	}

	public boolean validateClientAdminDocuments(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) @Valid ClientCompanyRegistration clientCompanyRegistrationInfo,
			StringBuffer message) {
		boolean doc1 = false;
		boolean doc2 = false;
		if (clientCompanyRegistrationInfo != null
				&& clientCompanyRegistrationInfo.getArrDocumentVOs() != null) {
			for (UploadDocumentVO documentVO : clientCompanyRegistrationInfo
					.getArrDocumentVOs()) {
				if (ConstantsAdmin.DOCUMENT_TYPE_IDNTY_COPY.equals(documentVO
						.getStrUploadDocumentType())) {
					doc1 = true;
				} else if (ConstantsAdmin.DOCUMENT_TYPE_POWER_OF_ATTORNEY
						.equals(documentVO.getStrUploadDocumentType())) {
					doc2 = true;
				}
			}
			if (ConstantsCommon.ENABLE
					.equalsIgnoreCase(clientCompanyRegistrationInfo
							.getStrAuthorizedPerson())) {
				doc2 = true;
			}
		}
		if (!doc1 && !doc2) {
			message.append("error.file.uploadall");
		} else if (!doc1) {
			message.append("error.upload.identification.copy");
		} else if (!doc2) {
			message.append("error.upload.power.of.attorney");
		} else {
			message.append("error.file.uploadall");
		}
		return doc1 && doc2;
	}

	public boolean uploadDocuments(
			HttpServletRequest request,
			SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) @Valid ClientCompanyRegistration clientCompanyRegistrationInfo)
			throws Exception {
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultiValueMap<String, MultipartFile> files = multipartRequest
				.getMultiFileMap();

		boolean uploaded = false;

		if (files != null) {

			@SuppressWarnings("rawtypes")
			Iterator iter = files.keySet().iterator();

			while (iter.hasNext()) {
				String str = (String) iter.next();
				List<MultipartFile> fileList = files.get(str);

				// String userFolderPath =
				// propertyConstants.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);

				for (MultipartFile mpf : fileList) {
					if (!(fileList.get(0)).isEmpty()) {

						String tempFileName = "" + System.currentTimeMillis();
						String fileExtension = FilenameUtils
								.getExtension(StringUtils.trim(mpf
										.getOriginalFilename()));

						String userFolderPath = propertyConstants
								.get(ConstantsAdmin.UPLOAD_USER_FILES_PATH_KEY);
						String tempFolderPath = propertyConstants
								.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);

						File uploadedFile = new File(tempFolderPath
								+ tempFileName + "." + fileExtension);
						FileOutputStream fos = new FileOutputStream(
								uploadedFile);
						fos.write(mpf.getBytes());
						fos.close();
						uploaded = true;

						UploadDocumentVO documentVO = new UploadDocumentVO();

						documentVO.setStrName(FilenameUtils.getName(mpf
								.getOriginalFilename()));
						// documentVO.setURL(userFolderPath +
						// clientCompanyRegistrationInfo.getStrCompNameEng() +
						// StringUtils.trim(mpf.getOriginalFilename()));
						documentVO.setURL(userFolderPath
								+ clientCompanyRegistrationInfo
										.getStrCompNameEng()
								+ FilenameUtils.getName(mpf
										.getOriginalFilename()));
						documentVO
								.setStrUploadDocumentType(clientCompanyRegistrationInfo
										.getStrUploadDocumentType());
						documentVO.setStrTempFileName(tempFileName + "."
								+ fileExtension);
						documentVO.setStrExtension(fileExtension);

						List<UploadDocumentVO> arrDocumentVOs;

						if (clientCompanyRegistrationInfo.getArrDocumentVOs() == null) {
							arrDocumentVOs = new ArrayList<UploadDocumentVO>();
						} else
							arrDocumentVOs = clientCompanyRegistrationInfo
									.getArrDocumentVOs();

						for (UploadDocumentVO uploadDocumentVO : arrDocumentVOs) {
							if (uploadDocumentVO.getStrUploadDocumentType()
									.equals(documentVO
											.getStrUploadDocumentType())) {
								throw new DuplicateMemberException(
										"Cannnot Add again");
							}
						}
						arrDocumentVOs.add(documentVO);

						clientCompanyRegistrationInfo
								.setArrDocumentVOs(arrDocumentVOs);

						// clientCompanyRegistrationInfo.setStrUploadURL(UPLOAD_FILES_TEMP_PATH
						// +
						// StringUtils.trimAllWhitespace(mpf.getOriginalFilename()));
						uploaded = true;

					}
				}
			}

		}

		return uploaded;
	}
	/*
	 * @RequestMapping(params = { "delete" }, method = RequestMethod.POST, value
	 * = "/form.htm") public String deleteTempFile( HttpServletRequest request,
	 * 
	 * @RequestParam(value = "row", required = true) String fileIndex,
	 * 
	 * @ModelAttribute(value =
	 * ConstantsAdmin.CLIENT_COMPANY_REGISTRATION_INFO_REQUEST_MODEL_KEY) @Valid
	 * ClientCompanyRegistration clientCompanyRegistrationInfo, BindingResult
	 * errors) throws IOException, NumberFormatException { boolean isDelete =
	 * WebUtils.hasSubmitParameter(request, ConstantsAdmin.DELETE_BUTTON); if
	 * (isDelete) { if (errors.hasErrors()) { return ViewUtils.DEFAULT_VIEW; }
	 * else { String tempFolderPath =
	 * propertyConstants.get(ConstantsAdmin.TEMP_UPLOAD_FILES_PATH_KEY);
	 * List<UploadDocumentVO> docs =
	 * clientCompanyRegistrationInfo.getArrDocumentVOs(); UploadDocumentVO doc =
	 * docs.get(Integer.valueOf(fileIndex)); if(doc != null){ File uploadedFile
	 * = new File(tempFolderPath + File.separator + doc.getStrTempFileName());
	 * FileUtils.forceDelete(uploadedFile);
	 * docs.remove(Integer.parseInt(fileIndex));
	 * request.setAttribute(ConstantsAdmin.DELETE_PARAM,
	 * doc.getStrUploadDocumentType());
	 * request.setAttribute(ConstantsAdmin.SUCCESS_PARAM,
	 * doc.getStrUploadDocumentType()); }else{ String[] messageArgs = new
	 * String[] { getMessageSource().getMessage("error.delete.file", null,
	 * RequestContextUtils.getLocale(request))}; errors.reject(messageArgs[0],
	 * null); } return ViewUtils.DEFAULT_VIEW; } } return
	 * ViewUtils.DEFAULT_VIEW;
	 * 
	 * }
	 */
}
